"""
__new__ 是 Python 中的一个特殊方法，用于创建类的实例。它与 __init__ 方法密切相关，但它们的功能有所不同。
"""
"""
1. __new__ 方法的作用
__new__ 方法负责创建类的实例，而 __init__ 方法负责初始化类的实例。换句话说，__new__ 是一个负责实例化对象的构造方法，它在 __init__ 之前被调用。

通常，__new__ 主要用于以下几种情况：

在创建实例时，做一些定制化的行为，比如单例模式。
继承自不可变类型（如 tuple、str）时，__new__ 可能需要被重写来确保正确的对象创建。
2. __new__ 和 __init__ 的区别
__new__ 是类的实例化方法，它创建并返回一个新对象（实例）。
__init__ 是对象创建后被自动调用的方法，用于对新对象进行初始化。
通常，__new__ 会返回一个新对象，而 __init__ 不返回任何内容，它只是对创建好的对象进行设置。
"""

"""
3. __new__ 的基本语法
__new__ 是一个类方法，定义时它接收 cls 作为第一个参数，表示类本身，接下来的参数是传给构造函数的参数。
"""
class MyClass:
    def __new__(cls, *args, **kwargs):
        print(f"Creating a new instance of {cls}")
        # 创建并返回一个新实例
        return super().__new__(cls)

    def __init__(self, value):
        self.value = value
        print(f"Initializing instance with value {self.value}")

# 创建实例
obj = MyClass(10)


"""
4. __new__ 的应用场景
1. 单例模式
在单例模式中，我们只希望一个类有一个实例，__new__ 可以帮助我们实现这一点。
"""

class Singleton:
    _instance = None

    def __new__(cls, *args, **kwargs):
        if cls._instance is None:
            cls._instance = super().__new__(cls)
        return cls._instance

# 创建多个实例
obj1 = Singleton()
obj2 = Singleton()

print(obj1 is obj2)  # 输出 True，obj1 和 obj2 是同一个实例

"""
2. 继承不可变类型
当你继承自不可变类型（如 tuple 或 str）时，__new__ 方法可能需要被重写，因为这些类型一旦创建后是不能修改的，所以必须在实例化时完全创建对象。
"""
class MyTuple(tuple):
    def __new__(cls, *args):
        # 创建并返回一个新的元组对象
        return super().__new__(cls, args)

t = MyTuple(1, 2, 3)
print(t)  # 输出 (1, 2, 3)

"""
3. 对象缓存
__new__ 也可以用于对象缓存或者对象重用的场景。如果我们希望相同的输入参数创建相同的对象，可以在 __new__ 中实现缓存机制。
"""
class CachedObject:
    _cache = {}

    def __new__(cls, value):
        if value not in cls._cache:
            instance = super().__new__(cls)
            cls._cache[value] = instance
        return cls._cache[value]

# 创建实例
obj1 = CachedObject(10)
obj2 = CachedObject(10)
print(obj1 is obj2)  # 输出 True，obj1 和 obj2 是同一个实例
